package com.tlvip.design.strategy.v2;

/**
 * <p>description：</p>
 * 改良成策略模式
 * JDK
 * Arrays.sort Comparator 排序时，只改变排序策略，不用动其他代码，实现不同排序方式
 * <p>
 * Spring
 * InstantiationStrategy 创建对象有很多方式，具体实现交给子类实现
 *
 *
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 2021/8/14</p>
 * Author mac
 *
 * @version 1.0
 */
public class StrategyTest {
    public static void main(String[] args) {
        // 本质上是组合，通过细粒度划分模块，再通过自由组合形成丰富的功能
        // 优点：修改关闭，拓展开放
        Zombie normalZombie = new NormalZombie();
        normalZombie.display();
        normalZombie.move();
        normalZombie.attack();

        // 可以灵活变更内部策略，而不用改其他代码，实现松耦合
        normalZombie.setAttackable(new HitAttack());
        normalZombie.attack();
        System.out.println("--------------");
//        Zombie zombie = new FlagZombie();
//        zombie.display();
//        zombie.move();
//        zombie.attack();

    }
}

/**
 * 策略-移动接口
 */
interface Moveable {
    void move();
}

/**
 * 策略-攻击接口
 */
interface Attackable {
    void attack();
}

/**
 * 僵尸父类
 */
abstract class Zombie {
    // 包含移动、攻击动作，显示名称
    public Zombie(Moveable moveable, Attackable attackable) {
        this.moveable = moveable;
        this.attackable = attackable;
    }

    // 延迟到子类中赋值
    Moveable moveable;

    // 延迟到子类中赋值
    Attackable attackable;

    abstract public void display();

    abstract void move();

    abstract void attack();

    public Moveable getMoveable() {
        return moveable;
    }

    public void setMoveable(Moveable moveable) {
        this.moveable = moveable;
    }

    public Attackable getAttackable() {
        return attackable;
    }

    public void setAttackable(Attackable attackable) {
        this.attackable = attackable;
    }
}

/**
 * 移动策略
 */
class StepByStepMoveable implements Moveable {

    @Override
    public void move() {
        System.out.println("一步一步移动");
    }
}

/**
 * 攻击策略-咬
 */
class BiteAttack implements Attackable {

    @Override
    public void attack() {
        System.out.println("咬");
    }
}

/**
 * 攻击策略-打
 */
class HitAttack implements Attackable {

    @Override
    public void attack() {
        System.out.println("打");
    }
}

/**
 * 旗手僵尸对象
 */
class FlagZombie extends Zombie {
    // 在构造方法中指定默认策略，在后面运行过程中可以动态替换，改变默认行为
    public FlagZombie() {
        super(new StepByStepMoveable(), new BiteAttack());
    }

    public FlagZombie(Moveable moveable, Attackable attackable) {
        super(moveable, attackable);
    }

    @Override
    public void display() {
        System.out.println("我是旗手僵尸");
    }

    @Override
    void move() {
        moveable.move();
    }

    @Override
    void attack() {
        attackable.attack();
    }
}

/**
 * 普通僵尸对象
 */
class NormalZombie extends Zombie {

    // 在构造方法中指定默认策略，在后面运行过程中可以动态替换，改变默认行为
    public NormalZombie() {
        super(new StepByStepMoveable(), new BiteAttack());
    }

    public NormalZombie(Moveable moveable, Attackable attackable) {
        super(moveable, attackable);
    }

    @Override
    public void display() {
        System.out.println("我是普通僵尸");
    }

    @Override
    void move() {
        moveable.move();
    }

    @Override
    void attack() {
        attackable.attack();
    }
}